<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        /*
        原型 prototype
          + 定义：每一个函数天生自带一个属性，叫做 prototype ，是一个对象
          + 构造函数也是函数，也会有这个自带的空间 prototype
          + 既然 prototype 是一个对象，我们就可以使用对象操作的语法，向里面添加一些内容

        对象
          + 定义：每一个对象，在你访问它的成员的时候，如果自己没有这个属性
            => 会自动去所属构造函数的 prototype 上查找
          + 自定义构造函数创建的对象也是对象，当你访问某一个成员的时候
            => 如果没有，也会去所属构造函数的原型上查找
            => 哪一个构造函数创建的对象，这个对象所属就属于哪一个构造函数
            => 因为构造函数在创建的对象的过程，我们起名为 实例化 的过程
              -> 创建出来的对象叫做这个构造函数的一个 实例化对象
        */

        function Person(){}

        Person.prototype.sayHi = function(){console.log('我是person原型上的方法')}
        
        console.log(Person.prototype)

        // 创建一个实例化对象
        // 因为 p1 是 Person 实例化出来的对象
        // p1 就是属于 Person 这个构造函数的
        // 当你去访问 p1 的 sayHi 成员的时候，p1  自己是没有的
        // 会自动去 Person 的 原型（prototype）上查找
        var p1 = new Person()
        console.log(p1)
        p1.sayHi()


        // 创建第二个实例化对象
        // 因为p2 也是Person 的实例化对象
        // p2 没有sayHi 成员，也会自动去 Person 的原型上查找
        var p2 = new Person()
        console.log(p2)
        p2.sayHi()


        // p1 的sayHi 方法和 p2 的sayHi 方法都是使用的 Person 构造函数的原型上的方法
        // 我只要向 Person 的原型上添加一些方法
        // 所有的Person 的每一个实例都可以使用
        // 且使用的都是同一个函数，不会出现浪费空间的行为

        console.log(p1.sayHi === p2.sayHi)
        // true  说明是一个函数
    </script>
</body>
</html>